/*
:::::::-.  ::::::.    :::.    ...     
 ;;,   `';,;;;`;;;;,  `;;; .;;;;;;;.  
 `[[     [[[[[  [[[[[. '[[,[[     \[[,
  $$,    $$$$$  $$$ "Y$c$$$$$,     $$$
  888_,o8P'888  888    Y88"888,_ _,88P
  MMMMP"`  MMM  MMM     YM  "YMMMMMP" 
:::::::-.  .,:::::: .-:::::'.,:::::::::.    :::.  .,-::::: .,::::::  
 ;;,   `';,;;;;'''' ;;;'''' ;;;;''''`;;;;,  `;;;,;;;'````' ;;;;''''  
 `[[     [[ [[cccc  [[[,,==  [[cccc   [[[[[. '[[[[[         [[cccc   
  $$,    $$ $$""""  `$$$"``  $$""""   $$$ "Y$c$$$$$         $$""""   
  888_,o8P' 888oo,__ 888     888oo,__ 888    Y88`88bo,__,o, 888oo,__ 
  MMMMP"`   """"YUMMM"MM,    """"YUMMMMMM     YM  "YUMMMMMP"""""YUMMM
           ___________________________________________
          /                                        /  \
         /                                        /__  |
        |       Dino Defence                     | /_\_|
        |       Team: Oasis                      |// \\
        |       Engine: Oasis v0.0.0.1           ||___||
        |       Genre: Arcade, Adventure, RPG    ||   ||
        |       Created: August 29, 2009         ||   ||
         \       Last Update: 8/29/09             \\_//
          \________________________________________\_/

*/

#include <irrlicht.h>
#include <iostream>
#include "scenetype.h"
#include "HUD.h"
#include "GUI.h"
#include "input.h"
#include "usermovement.h"

using namespace irr;
using namespace core;
using namespace video;
using namespace scene;
using namespace std;



int main()
{
	SmoothEventReceiver	*receiver = SmoothEventReceiver.createReceiver();

	//Load Profile From Directory
	if( ! info )
		profile	*info = new profile;
	else
	{
		//Read Saved Profile
		if( info->Name )
		//Write Default Profile
		else
		{
			info->Name	= "Placeasaur";
			info->Mesh	= "media/dino.b3d";
			info->Skill	= "Meele";
		}
	}

	IrrlichtDevice      *device = createDevice( profile::Video::DriverType,
		dimension2d<s32>( 640, 480 ), 32, false, false, false, &receiver );

	if( device == 0 )
		return 1; // could not create selected driver.

	array<SJoystickInfo> joystickInfo;
	if( device->activateJoysticks( joystickInfo ))
	{
		cout << "Joystick support is enabled and " << joystickInfo.size() << " joystick(s) are present." << endl;

		for( u32 joystick = 0; joystick < joystickInfo.size(); ++joystick)
		{
			cout << "Joystick " << joystick << ":" << endl;
			cout << "\tName: '" << joystickInfo[joystick].Name.c_str() << "'" << endl;
			cout << "\tAxes: " << joystickInfo[joystick].Axes << endl;
			cout << "\tButtons: " << joystickInfo[joystick].Buttons << endl;

			cout << "\tHat is: ";

			switch( joystickInfo[joystick].PovHat )
			{
			case SJoystickInfo::POV_HAT_PRESENT:
				cout << "present" << endl;
				break;

			case SJoystickInfo::POV_HAT_ABSENT:
				cout << "absent" << endl;
				break;

			case SJoystickInfo::POV_HAT_UNKNOWN:
			default:
				cout << "unknown" << endl;
				break;
			}
		}
	}
	else
	{
		cout << "Joystick support is not enabled." << endl;
	}

	stringw tmp = L"Oasis v0.1(";
	tmp += joystickInfo.size();
	tmp += " joysticks)";
	device->setWindowCaption( tmp.c_str());

    IVideoDriver	*driver	= device->getVideoDriver();
	ISceneManager	*smgr	= device->getSceneManager();
	IGUIEnvironment	*env	= device->getGUIEnvironment();

	while( device->run())
	{
		driver->beginScene( true, true, SColor( 255, 106, 181, 255 ));

		//Game State
		switch( GamSte )
		{
			//Introduction
			case "Introduction":
				if( env->iswindowactive())
					env.drawAll();
				break;

			//Loading
			case "Loading":
				map         *game = map::Initialize(
					profile::Lineup );

				RPGCamera	*camera = RPGCamera::Initialize(
					null,
					null,
					"Spectate",
					info->View[0] );
					
				user		*player = user::Initialize(
					null,
					null,
					info->Mesh,
					info->Name,
					info->Skill,
					info->Weapon,
					info->Item );

				//camera->
				
				//Render Scene
				if( env->iswindowactive())
					env->drawAll();
				break;

			//Playing
			case "Playing":
				//Update Movement
				player->Update();

				//Update Camera
				RPGCamera->Update();
				/*Line.setLineFromVects( Cam.Node.getAbsolutePosition(),
					Line.getStart().Plus(( Cam.Node.getTarget().Minus( Line.getStart())).normalize().Mult( 1000.0 )));

				If( smgr.getSceneCollisionManager().getCollisionPoint(
					Line, Slc, Intersection, Tri ))
				{
					driver->SetTransform( ETS_WORLD, Matrix4.create());
					driver->draw3DTriangle( player.Trişş, Null );
				}*/

				//Calculate Scene
				projectile.Update();

				//Render Scene
				if( env->iswindowactive())
				{
					smgr->drawAll();

					//Render HUD
					infoHUD( Amm, Hth, WpnInf, ItmInf, AphInd, ActTmr, ActAcc, Eqp );

					//Render GUI
					env.drawAll();
				}

				gameEvent( GmeMde );
				break;

			//Accomplished
			case "Accomplished":

			//Failed
			case "Failed":

			//Paused
			case "Paused":
				if( env->isWindowactive())
				{
					smgr->drawAll();

					//Render HUD
					//infoHUD( Amm, Hth, WpnInf, ItmInf, AphInd, ActTmr, ActAcc, Eqp );

					//Render GUI
					env.drawAll();
				}
				
				gameEvent( GmeMde );
				break;
				
			//Spectating
			case "Spectating":

			//Dead
			case "Dead":
			default:
		}

		if( profile.Debug )
		{
			FPS = driver->getFPS();
			if( LastFPS || FPS ) LastFPS = FPS;

			string		Str			= "Oasis - Irrlicht v1.5";
			string		Str			+= " [ " + driver->getName() + " ]";
			string		Str			+= " | FPS: " + LastFPS;

			vector3df	UsrPos2		= player.Nde.getAbsolutePosition();
			vector3df	CamPos2		= RPGCamera.Nde.getAbsolutePosition();
			float		CamDstHrz2	= vector3df( UsrPos2.getX(), 0, UsrPos2.getZ()).getDistanceFrom( vector3df( CamPos2.getX(), 0, CamPos2.getZ()));
			float		CamDstVrt2	= CamPos2.getY() - UsrPos2.getY();
			float		FwdAng2		= vector2df( CamPos2.getX() - UsrPos2.getX(), CamPos2.getZ() - UsrPos2.getZ()).getAngle();

			string		Str2		= "SrfAng: " + int( SrfAngTst );
			string		Str2		+= " | TriCnt: " + driver->getPrimitiveCountDrawn();
			//string	Str2		+= " | Spd: " + Vector2df.createFromVals( player.Vel.getX(), player.Vel.getZ()).getLength();
			//string	Str2		+= " | NdeRot: " + player.Nde.GetRotation().getY();
			//string	Str2		+= " | MotVelRot: " + MotVelTst.getY();
			//string	Str2		+= " | MotVelAng: " + Int( MotVelTst.getX()) + ", " + Int( MotVelTst.getY()) + ", " + Int( MotVelTst.getZ());
			string		Str2		+= " | LndPos: " + int( LndPosTst.getX()) + ", " + int( LndPosTst.getY()) + ", " + int( LndPosTst.getZ());
			//string	Str2		+= " | CrsAng: " + CrsAng;
			//string	Str2		+= " | TriNrm: " + TriNrm.normalize().getX() + ", " + TriNrm.normalize().getY() + ", " + TriNrm.normalize().getZ();
			//string	Str2		+= " | Landed: " + FallTest;
			//string	Str2		+= " | Bumped: " + BumpTest;
			//string	Str2		+= " | FwdAng: " + FwdAng2;
			//string	Str2		+= " | AphInd: " + AphInd[1];
			//string	Str2		+= " | ActTmr: " + ActTmr[0];
			//string	Str2		+= " | Prj: " + projectile.Cnt.Count();
			//string	Str2		+= " | CamDstHrz: " + CamDstHrz2;
			//string	Str2		+= " | CamDstVrt: " + CamDstVrt2;
			//string	Str2		+= " | NdeRot: " + player.Nde.GetRotation().getY();
			//string	Str2		+= " | Position: " + Int( player.Nde.getPosition().getX()) + ", "  + Int( player.Nde.getPosition().getY()) + ", " + Int( player.Nde.getPosition().getZ());
			string		Str2		+= " | State: " + player.Ste;
			string		Str2		+= " | Vel: " + int( player.Vel.getX()) + ", " + int( player.Vel.getY()) + ", " + int( player.Vel.getZ());

			//Render Debug Information
			SMaterial	LinMat	= SMaterial.Create();

			LinMat.setFlag( EMF_LIGHTING, False );
			driver->setMaterial( LinMat );

			driver->draw3DTriangle( player.Tri, _SCOLOR( 255, 255, 255, 255 ));
			driver->draw3DLine( player.Nde.getAbsolutePosition(), player.Nde.getAbsolutePosition().Plus( player.Vel.Mult( 20 )), _SCOLOR( 255, 255, 0, 0 ));
			driver->draw3DLine( player.Nde.getAbsolutePosition(), player.Nde.getAbsolutePosition().Minus( MotVelTst ), _SCOLOR( 255, 0, 0, 255 ));
			driver->draw3DLine( player.Nde.getAbsolutePosition(), LndPosTst, SColor.createFromVals( 255, 0, 255, 0 ));
			GUIFont.Draw( Str,
				rect<s32>( 0, 0, 256, 12 ),
				SColor( 255, 255, 255, 255 ));
			GUIFont.Draw( "Debug Information:",
				rect<s32>( 0, 12, 256, 24 ),
				SColor( 255, 255, 255, 255 ));
			GUIFont.Draw( Str2,
				rect<s32>( 0, 24, 256, 36 ),
				SColor( 255, 255, 255, 255 ));
		}
		driver->EndScene();
	}
	device->drop();

	return 1;
};
